package com.base.demo.design.test.basesingletondesign;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @Description: 输出流文件
 * @BelongsProject: base-demo-design
 * @BelongsPackage: com.base.demo.design.basesingletondesign
 * @Author: ChenYongJia
 * @CreateTime: 2022-06-07 14:31
 * @Email: chen87647213@163.com
 * @Version: 1.0
 */
public class FileOutputStreamDemo02 {

    /**
     * FileOutputStream：文件输出流用于将数据写入文件File
     * 使用字节输出流写数据的步骤
     * 1.创建字节输出流对象（调用系统功能创建了文件，创建字节输出流对象，让字节输出流对象指向文件）
     * 2.调用字节输出流对象的写数据方法
     * 3.释放资源（关闭此输出流并释放与此流相关联的任何系统资源）
     *
     * @return void
     * @date 2022/6/7 14:33
     * @author ChenYongJia
     * @version 1.0
     */
    public void aaa() throws IOException {
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt");
        /*
        这里创建了字节输出流对象 fos
        创建字节输出流对象这里一共有三步操作：
        1.调用了系统功能创建了文件
        2.创建了字节流输出对象
        3.让字节输出流对象指向创建好的文件
         */
        fos.write(97);//写到低层是97（ASCII码），但是我们打开文件内容是a
        fos.write(57);
        fos.write(55);

        fos.close();//释放资源，关闭此文件输出流释放并与此流相关联的任何系统资源
    }

    // ================= 字节流写数据的3种方式 ===================
    /**
     * void write(int b)
     * 将指定的字节写入到此文件输出流，一次写一个字节数据
     *
     * @return void
     * @date 2022/6/7 14:33
     * @author ChenYongJia
     * @version 1.0
     */
    public void bbb() throws IOException {
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt");
        fos.write(97);
        fos.close();
    }

    /**
     * void write(byte[] b)
     * 将b.length字节从指定的字节数组写入此文件输出流，一次写一个字节数组数据
     *
     * @return void
     * @date 2022/6/7 14:34
     * @author ChenYongJia
     * @version 1.0
     */
    public void ccc() throws IOException {
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt");
        byte[] bys = {97,98,99,100,101};
        fos.write(bys);
        fos.close();
    }

    /**
     * void write(byte[] b, int off, int len)
     * 将len字节从指定的字节数组开始，从偏移量off开始写入此文件输出流，一次写一个字节数组的部分数据
     *
     * @return void
     * @date 2022/6/7 14:34
     * @author ChenYongJia
     * @version 1.0
     */
    public void ddd() throws IOException {
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt");
        byte[] bs1 = "abcdefghijk".getBytes(StandardCharsets.UTF_8);
        fos.write(bs1,0,1);//从索引off开始，写length个字节
        fos.close();
    }

    // ==================  PS：String类中有getBytes()可以获取字符串的字节，返回字符串对应的字节数组 ===================

    /**
     * 字节流写数据的两个小问题
     * 1.字节流写数据如何实现换行？（\n换行,\r\n,\r）
     *
     * @return void
     * @date 2022/6/7 14:36
     * @author ChenYongJia
     * @version 1.0
     */
    public void eee() throws IOException {
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt");
        for(int i=0;i<10;i++){
            fos.write("hello".getBytes(StandardCharsets.UTF_8));
            fos.write("\n".getBytes(StandardCharsets.UTF_8));//  \n换行
        }
        fos.close();
    }

    /**
     * 字节流写输出如果实现追加写入？（构造方法中的参数boolean append）
     * FileOutputStream的构造方法：
     *
     * public FileOutputStream(String name,
     *                         boolean append)
     *                  throws FileNotFoundException
     * 这里有带boolean append，如果为true，会从文件的末尾写入数据。
     * 默认是false，从文件的开头写入数据。
     *
     * @return void
     * @date 2022/6/7 14:36
     * @author ChenYongJia
     * @version 1.0
     */
    public void fff() throws IOException {
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt",true);
        for(int i=0;i<10;i++){
            fos.write("hello".getBytes(StandardCharsets.UTF_8));
            fos.write("\n".getBytes(StandardCharsets.UTF_8));//  \n换行
        }
        for (int i=0;i<10;i++){
            fos.write("world".getBytes());
            fos.write("\n".getBytes(StandardCharsets.UTF_8));
        }
        fos.close();
    }

    /**
     * 字节流写数据加异常处理
     * 一般直接在外面包try{}catch{}，但是会有一个问题，如果写入数据失败会运行catch的内容，但是close方法没有运行到也就是资源没有被释放。所以在io操作一定要保存内存被释放。
     *
     * 提供了finally块来执行所有清除操作
     * finally：在异常处理时提供finally块来执行所有清除的操作。比如io流中的资源释放。
     * 特点：被finally块控制的语句一定会执行，除非JVM退出
     *
     * @return void
     * @date 2022/6/7 14:38
     * @author ChenYongJia
     * @version 1.0
     */
    public void ggg() throws IOException {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("src\\dailyioStream\\fos.txt");
            fos.write("hello".getBytes(StandardCharsets.UTF_8));
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (fos!=null){
                try {
                    fos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 字节流读数据（一次读一个字节数据）
     * 需求：把文件fos.txt中的内容读取出来在控制台输出
     *
     * FileInputStream：从文件系统中的文件获取输入字节
     * 使用字节输入流读数据的步骤：
     * 1.创建字节输入流对象
     * 2.调用字节输入流对象的读数据方法
     * 3.释放资源
     *
     * FileInputStream(String name)：通过打开一个文件的连接来创建一个FileInputStream
     *
     * @return void
     * @date 2022/6/7 14:39
     * @author ChenYongJia
     * @version 1.0
     */
    public void hhh() throws IOException {
        FileInputStream fis = new FileInputStream("src\\dailyioStream\\fos.txt");
        int read;
        // 循环读取文件所有内容
        while((read=fis.read()) !=-1){
            System.out.print((char) read);
        }
        fis.close();
    }

    /**
     * 复制文本文件
     * 分析：
     * 1、复制文本文件，其实就是把文本文件的内容从一个文件中读取出来（数据源），然后写入到另外一个文件中（目的地）
     * 2、数据源：
     * ”E:\it\java.txt“—读数据—InputStream—FileInputStream
     * 3、目的地：
     * “src\dailyioStream\java.txt”—写数据—OutputStream—FileOutputStream
     *
     * 思路：
     * 1、根本数据源创建字节输入流对象
     * 2、根据目的地创建字节输出流对象
     * 3、读写数据，复制文本文件（一次读取一个字节，一次写入一个字节）
     *
     * @return void
     * @date 2022/6/7 14:40
     * @author ChenYongJia
     * @version 1.0
     */
    public void iii() throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\n\\Desktop\\personal\\javaDemo\\java\\案例.txt");
        FileOutputStream fos = new FileOutputStream("src\\dailyioStream\\fos.txt");

        int bys;
        bys = fis.read();
        while ((bys=fis.read()) != -1){
            fos.write(bys);
        }
        fis.close();
        fos.close();
    }

}
